#include <QFile>
#include <QTextStream>
#include <QStringList>

#include "CoreIni.h"


CoreIni::CoreIni(QObject* parent, QString name) : QObject(parent) {
	setObjectName(name);
}

CoreIni::~CoreIni() {
}

void CoreIni::Load(const QString& file, int& res) {
	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::Load", QStringList());
		return;
	}

	QFile f(file);

	//проверяем что файл существует
	if (!f.exists()) {
		res=2;
		emit SetCurrentError(res, "CoreIni::Load", QStringList() << file);
		return;
	}

	//пытаемся открыть файл
	bool ok = f.open(QIODevice::ReadOnly);
	//проверяем открылся ли файл
	if (!ok) {
		res=3;
		emit SetCurrentError(res, "CoreIni::Load", QStringList() << file);
		return;
	}

	//создаем поток для чтения из файла
	QTextStream stream( &f );
	
	//создаем начальные значения
	QString sec = "";
	while ( !stream.atEnd() ) {
		//читываем строку
		QString str = stream.readLine();

		//проверяем длину строки
		if (str.length() < 2) { continue; }

		//проверяем что это имя секции
		if (str.left(1) == "[" && str.right(1) == "]") {
			sec = str.mid(1, str.length()-2);
			continue;
		}

		//проверяем что элемент находится в какой-то секции
		if (sec.isEmpty()) { continue; }
		
		//проверяем что это параметр
		if (str.indexOf("=") < 1) { continue; }
		
		QStringList w = str.split("=");
		//проверяем что в параметре нет пробела
		if (w[0].contains(" ") > 0) { continue; }
		
		//сохраняем значение в массив
		files[file][sec][w[0]] = str.mid(w[0].length()+1);
		
	}
	
	//закрываем файл
	f.close();
	
	//сигнал загрузки файла
	emit IniFileLoaded(file);

	res=0;
	emit SetCurrentError(res, "CoreIni::Load", QStringList() << file);
}

void CoreIni::Load(const QString& file, bool& res) {
	int r;
	Load(file, r);
	res = (r <= 0);
}

void CoreIni::Load(const QString& file) {
	int r;
	Load(file, r);
}

void CoreIni::Save(const QString& file, int& res) {
	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::Save", QStringList());
		return;
	}

	//проверяем что такой файл открыт
	if (files.find(file) == files.end()) {
		res=2;
		emit SetCurrentError(res, "CoreIni::Save", QStringList() << file);
		return;
	}

	QFile f(file);

	//пытаемся открыть файл
	bool ok = f.open(QIODevice::WriteOnly);
	//проверяем открылся ли файл
	if (!ok) {
		res=3;
		emit SetCurrentError(res, "CoreIni::Save", QStringList() << file);
		return;
	}

	//создаем поток для чтения из файла
	QTextStream stream( &f );

	//перебираем все секции
	SECTION::iterator its;
	for(its = files[file].begin(); its != files[file].end(); ++its) {
		//записываем имя секции
		stream << "[" << its->first << "]\n";
		
		//перебираем список параметров
		PARAM::iterator itp;
		for (itp = its->second.begin(); itp != its->second.end(); ++itp) {
			stream << itp->first << "=" << itp->second << "\n";
		}
		
		//делаем отступ после секции
		stream << "\n";
	}
	//закрываем файл
	f.close();

	//сигнал сохранения файла
	emit IniFileSaved(file);

	res=0;
	emit SetCurrentError(res, "CoreIni::Save", QStringList() << file);
}

void CoreIni::Save(const QString& file, bool& res) {
	int r;
	Save(file, r);
	res = (r <= 0);
}

void CoreIni::Save(const QString& file) {
	int r;
	Save(file, r);
}

void CoreIni::SaveAll(int& res) {
	//перебираем все файлы
	FILES::iterator it;
	for (it = files.begin(); it != files.end(); ++it) {
		Save(it->first, res);
	}

	//сигнал сохранения всех файлов
	emit AllIniFilesSaved();

	res = 0;
	emit SetCurrentError(res, "CoreIni::UnloadAll", QStringList());
}

void CoreIni::SaveAll(bool& res) {
	int r;
	SaveAll(r);
	res = (r <= 0);
}

void CoreIni::SaveAll() {
	int r;
	SaveAll(r);
}

void CoreIni::Unload(const QString& file, int& res) {
	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::Unload", QStringList());
		return;
	}

	//удаляем файл из массива
	files.erase(file);

	//сигнал выгрузки файла
	emit IniFileUnloaded(file);

	res = 0;
	emit SetCurrentError(res, "CoreIni::Unload", QStringList());
}

void CoreIni::Unload(const QString& file, bool& res) {
	int r;
	Unload(file, r);
	res = (r <= 0);
}

void CoreIni::Unload(const QString& file) {
	int r;
	Unload(file, r);
}

void CoreIni::UnloadAll(int& res) {
	//удаляем все записи
	files.clear();

	//сигнал выгрузки всех файлов
	emit AllIniFilesUnloaded();

	res = 0;
	emit SetCurrentError(res, "CoreIni::UnloadAll", QStringList());
}

void CoreIni::UnloadAll(bool& res) {
	int r;
	UnloadAll(r);
	res = (r <= 0);
}

void CoreIni::UnloadAll() {
	int r;
	UnloadAll(r);
}

void CoreIni::GetFileList(QStringList& filelist) {
	//на всякий случай очищаем список файлов
	filelist.clear();
	
	//перебираем все файлы
	FILES::iterator it;
	for (it = files.begin(); it != files.end(); ++it) {
		filelist << it->first;
	}
}

void CoreIni::isOpen(const QString& file, int& res) {
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::isOpen", QStringList());
		return;
	}

	//проверяем был ли открыт файл
	if (files.find(file) != files.end()) {
		res=2;
		emit SetCurrentError(res, "CoreIni::isOpen", QStringList() << file);
		return;
	}

	res = 0;
	emit SetCurrentError(res, "CoreIni::isOpen", QStringList());
}

void CoreIni::isOpen(const QString& file, bool& res) {
	int r;
	isOpen(file, r);
	res = (r <= 0);
}

void CoreIni::GetSectionList(const QString& file, QStringList& seclist, int& res) {
	//очищаем список секций
	seclist.clear();

	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::GetSectionList", QStringList());
		return;
	}

	//флаг необходимости загрузки файла
	bool needopen = false;
	//проверяем что такой файл открыт
	if (files.find(file) == files.end()) {
		//ставим флаг что надо загружать файл
		needopen = true;
		//загружаем файл
		int res1;
		Load(file, res1);
		//проверяем получилось ли загрузить файл
		if (res1 > 0) {
			res=2;
			emit SetCurrentError(res, "CoreIni::GetSectionList", QStringList() << file);
			return;
		}
	}

	//считываем список секций
	SECTION::iterator it;
	for (it = files[file].begin(); it != files[file].end(); ++it) {
		seclist << it->first;
	}

	//провеяем был ли загружен файл и если был - закрываем
	if (needopen) {
		//выгружаем файл
		Unload(file, res);
		if (res > 0) {
			res=3;
			emit SetCurrentError(res, "CoreIni::GetSectionList", QStringList() << file);
			return;
		}
	}

	res = 0;
	emit SetCurrentError(res, "CoreIni::GetSectionList", QStringList());
}

void CoreIni::GetSectionList(const QString& file, QStringList& seclist, bool& res) {
	int r;
	GetSectionList(file, seclist, r);
	res = (r <= 0);
}

void CoreIni::GetSectionList(const QString& file, QStringList& seclist) {
	int r;
	GetSectionList(file, seclist, r);
}

void CoreIni::RenameSection(const QString& file, const QString& sec, const QString& newsec, int& res) {
	//копируем секцию
	CopySection(file, sec, newsec, res);

	//проверяем скопировалось или нет
	if (res > 0) { return; }

	//удаляем оригинал
	files[file].erase(sec);
	
	res = 0;
	emit SetCurrentError(res, "CoreIni::RenameSection", QStringList());
}


void CoreIni::RenameSection(const QString& file, const QString& sec, const QString& newsec, bool& res) {
	int r;
	RenameSection(file, sec, newsec, r);
	res = (r <= 0);
}

void CoreIni::RenameSection(const QString& file, const QString& sec, const QString& newsec) {
	int r;
	RenameSection(file, sec, newsec, r);
}

void CoreIni::CopySection(const QString& file, const QString& sec, const QString& newsec, int& res) {
	//проверяем что мы не копируем сами в себя
	if (sec == newsec) {
		res = 0;
		emit SetCurrentError(res, "CoreIni::CopySection", QStringList());
		return;
	}

	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::CopySection", QStringList());
		return;
	}

	//флаг необходимости загрузки файла
	bool needopen = false;
	//проверяем что такой файл открыт
	if (files.find(file) == files.end()) {
		 needopen = true;
		//загружаем файл
		int res1;
		Load(file, res1);
		//проверяем получилось ли загрузить файл
		if (res1 > 0) {
			res=4;
			emit SetCurrentError(res, "CoreIni::CopySection", QStringList() << file);
			return;
		}
	}

	//проверяем имя секции на пустоту
	if (sec.isEmpty()) {
		res=2;
		emit SetCurrentError(res, "CoreIni::CopySection", QStringList() << file);
		return;
	}

	//проверяем новое имя секции на пустоту
	if (newsec.isEmpty()) {
		res=3;
		emit SetCurrentError(res, "CoreIni::CopySection", QStringList() << file);
		return;
	}

	//устанавливаем ошибки по умолчанию
	QStringList err;
	res = 0;
	//проверяем что секция существует
	if (files[file].find(sec) == files[file].end()) {
		//секция не существует, пишем ошибки
		res = 4;
		err << file << sec;
	} else {
		//секция существует, копируем
		files[file][newsec] = files[file][sec];
	}

	//провеяем был ли загружен файл и если был - закрываем
	if (needopen) {
		//выгружаем файл
		Unload(file, res);
		if (res > 0) {
			res=5;
			emit SetCurrentError(res, "CoreIni::CopySection", QStringList() << file);
			return;
		}
	}

	emit SetCurrentError(res, "CoreIni::CopySection", err);
}

void CoreIni::CopySection(const QString& file, const QString& sec, const QString& newsec, bool& res) {
	int r;
	CopySection(file, sec, newsec, r);
	res = (r <= 0);
}

void CoreIni::CopySection(const QString& file, const QString& sec, const QString& newsec) {
	int r;
	CopySection(file, sec, newsec, r);
}

void CoreIni::DelSection(const QString& file, const QString& sec, int& res) {
	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::DelSection", QStringList());
		return;
	}

	//флаг необходимости загрузки файла
	bool needopen = false;
	//проверяем что такой файл открыт
	if (files.find(file) == files.end()) {
		 needopen = true;
		//загружаем файл
		int res1;
		Load(file, res1);
		//проверяем получилось ли загрузить файл
		if (res1 > 0) {
			res=4;
			emit SetCurrentError(res, "CoreIni::DelSection", QStringList() << file);
			return;
		}
	}

	//проверяем имя секции на пустоту
	if (sec.isEmpty()) {
		if (needopen) { Unload(file, res); }
		res=2;
		emit SetCurrentError(res, "CoreIni::DelSection", QStringList() << file);
		return;
	}

	//устанавливаем ошибки по умолчанию
	QStringList err;
	res = 0;
	//проверяем что секция существует
	if (files[file].find(sec) == files[file].end()) {
		//секция не существует
		res = -1;
		err << file << sec;
	} else {
		//секция существует, удаляем
		files[file].erase(sec);
	}

	//провеяем был ли загружен файл и если был - закрываем
	if (needopen) {
		//выгружаем файл
		Unload(file, res);
		if (res > 0) {
			res=5;
			emit SetCurrentError(res, "CoreIni::DelSection", QStringList() << file);
			return;
		}
	}

	emit SetCurrentError(res, "CoreIni::DelSection", err);
}

void CoreIni::DelSection(const QString& file, const QString& sec, bool& res) {
	int r;
	DelSection(file, sec, r);
	res = (r <= 0);
}

void CoreIni::DelSection(const QString& file, const QString& sec) {
	int r;
	DelSection(file, sec, r);
}

void CoreIni::GetParamList(const QString& file, const QString& sec, QStringList& parlist, int& res) {
	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::GetParamList", QStringList());
		return;
	}

	//флаг необходимоcти загрузки файла
	bool needopen = false;
	//проверяем что такой файл открыт
	if (files.find(file) == files.end()) {
		 needopen = true;
		//загружаем файл
		int res1;
		Load(file, res1);
		//проверяем получилось ли загрузить файл
		if (res1 > 0) {
			res=4;
			emit SetCurrentError(res, "CoreIni::GetParamList", QStringList() << file);
			return;
		}
	}

	//проверяем имя секции на пустоту
	if (sec.isEmpty()) {
		if (needopen) { Unload(file, res); }
		res=2;
		emit SetCurrentError(res, "CoreIni::GetParamList", QStringList() << file);
		return;
	}

	//проверяем что секция существует
	if (files[file].find(sec) == files[file].end()) {
		if (needopen) { Unload(file, res); }
		res=3;
		emit SetCurrentError(res, "CoreIni::GetParamList", QStringList() << file << sec);
		return;
	}

	//считываем список параметров
	PARAM::iterator it;
	for (it = files[file][sec].begin(); it != files[file][sec].end(); ++it) {
		parlist << it->first;
	}

	//провеяем был ли загружен файл и если был - закрываем
	if (needopen) {
		//выгружаем файл
		Unload(file, res);
		if (res > 0) {
			res=5;
			emit SetCurrentError(res, "CoreIni::GetParamList", QStringList() << file);
			return;
		}
	}

	res = 0;
	emit SetCurrentError(res, "CoreIni::GetParamList", QStringList());
}

void CoreIni::GetParamList(const QString& file, const QString& sec, QStringList& parlist, bool& res) {
	int r;
	GetParamList(file, sec, parlist, r);
	res = (r <= 0);
}

void CoreIni::GetParamList(const QString& file, const QString& sec, QStringList& parlist) {
	int r;
	GetParamList(file, sec, parlist, r);
}

void CoreIni::GetValue(const QString& file, const QString& sec, const QString& par, QString& val, int& res) {
	//устанавливаем начальное значение
	val = "";

	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::GetValue", QStringList());
		return;
	}

	//флаг необходимоcти загрузки файла
	bool needopen = false;
	//проверяем что такой файл открыт
	if (files.find(file) == files.end()) {
		 needopen = true;
		//загружаем файл
		int res1;
		Load(file, res1);
		//проверяем получилось ли загрузить файл
		if (res1 > 0) {
			res=5;
			emit SetCurrentError(res, "CoreIni::GetValue", QStringList() << file);
			return;
		}
	}

	//проверяем имя секции на пустоту
	if (sec.isEmpty()) {
		if (needopen) { Unload(file, res); }
		res=2;
		emit SetCurrentError(res, "CoreIni::GetValue", QStringList() << file);
		return;
	}

	//проверяем имя параметра на пустоту
	if (par.isEmpty()) {
		if (needopen) { Unload(file, res); }
		res=3;
		emit SetCurrentError(res, "CoreIni::GetValue", QStringList() << file << sec);
		return;
	}

	//проверяем что секция существует
	if (files[file].find(sec) == files[file].end()) {
		if (needopen) { Unload(file, res); }
		res=4;
		emit SetCurrentError(res, "CoreIni::GetValue", QStringList() << file << sec);
		return;
	}

	//проверяем что параметр существует
	if (files[file][sec].find(par) == files[file][sec].end()) {
		if (needopen) { Unload(file, res); }
		res=-1;
		emit SetCurrentError(res, "CoreIni::GetValue", QStringList() << file << sec << par);
		return;
	}

	//считываем значение параметра
	val = files[file][sec][par];

	//провеяем был ли загружен файл и если был - закрываем
	if (needopen) {
		//выгружаем файл
		Unload(file, res);
		if (res > 0) {
			res=6;
			emit SetCurrentError(res, "CoreIni::GetValue", QStringList() << file);
			return;
		}
	}

	res = 0;
	emit SetCurrentError(res, "CoreIni::GetValue", QStringList());
}

void CoreIni::GetValue(const QString& file, const QString& sec, const QString& par, QString& val, bool& res) {
	int r;
	GetValue(file, sec, par, val, r);
	res = (r <= 0);
}

void CoreIni::GetValue(const QString& file, const QString& sec, const QString& par, QString& val) {
	int r;
	GetValue(file, sec, par, val, r);
}

void CoreIni::SetValue(const QString& file, const QString& sec, const QString& par, const QString& val, int& res) {
	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::SetValue", QStringList());
		return;
	}

	//флаг необходимоcти загрузки файла
	bool needopen = false;
	//проверяем что такой файл открыт
	if (files.find(file) == files.end()) {
		 needopen = true;
		//загружаем файл
		int res1;
		Load(file, res1);
		//проверяем получилось ли загрузить файл
		if (res1 > 0) {
			res=6;
			emit SetCurrentError(res, "CoreIni::SetValue", QStringList() << file);
			return;
		}
	}

	//проверяем имя секции на пустоту
	if (sec.isEmpty()) {
		if (needopen) { Unload(file, res); }
		res=2;
		emit SetCurrentError(res, "CoreIni::SetValue", QStringList() << file);
		return;
	}

	//проверяем имя параметра на пустоту
	if (par.isEmpty()) {
		if (needopen) { Unload(file, res); }
		res=3;
		emit SetCurrentError(res, "CoreIni::SetValue", QStringList() << file << sec);
		return;
	}

	//проверяем что секция существует
	if (files[file].find(sec) == files[file].end()) {
		if (needopen) { Unload(file, res); }
		res=4;
		emit SetCurrentError(res, "CoreIni::SetValue", QStringList() << file << sec);
		return;
	}

	//проверяем что параметр существует
	if (files[file][sec].find(par) == files[file][sec].end()) {
		if (needopen) { Unload(file, res); }
		res=5;
		emit SetCurrentError(res, "CoreIni::SetValue", QStringList() << file << sec << par);
		return;
	}

	//устанавливаем значение параметра
	files[file][sec][par] = val;

	//провеяем был ли загружен файл и если был - закрываем
	if (needopen) {
		//выгружаем файл
		Unload(file, res);
		if (res > 0) {
			res=7;
			emit SetCurrentError(res, "CoreIni::SetValue", QStringList() << file);
			return;
		}
	}

	res = 0;
	emit SetCurrentError(res, "CoreIni::SetValue", QStringList());
}

void CoreIni::SetValue(const QString& file, const QString& sec, const QString& par, const QString& val, bool& res) {
	int r;
	SetValue(file, sec, par, val, r);
	res = (r <= 0);
}

void CoreIni::SetValue(const QString& file, const QString& sec, const QString& par, const QString& val) {
	int r;
	SetValue(file, sec, par, val, r);
}

void CoreIni::DelParam(const QString& file, const QString& sec, const QString& par, int& res) {
	//проверяем имя файла на пустоту
	if (file.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CoreIni::DelParam", QStringList());
		return;
	}

	//флаг необходимоcти загрузки файла
	bool needopen = false;
	//проверяем что такой файл открыт
	if (files.find(file) == files.end()) {
		 needopen = true;
		//загружаем файл
		int res1;
		Load(file, res1);
		//проверяем получилось ли загрузить файл
		if (res1 > 0) {
			res=6;
			emit SetCurrentError(res, "CoreIni::DelParam", QStringList() << file);
			return;
		}
	}

	//проверяем имя секции на пустоту
	if (sec.isEmpty()) {
		if (needopen) { Unload(file, res); }
		res=2;
		emit SetCurrentError(res, "CoreIni::DelParam", QStringList() << file);
		return;
	}

	//проверяем имя параметра на пустоту
	if (par.isEmpty()) {
		if (needopen) { Unload(file, res); }
		res=3;
		emit SetCurrentError(res, "CoreIni::DelParam", QStringList() << file << sec);
		return;
	}

	//проверяем что секция существует
	if (files[file].find(sec) == files[file].end()) {
		if (needopen) { Unload(file, res); }
		res=4;
		emit SetCurrentError(res, "CoreIni::DelParam", QStringList() << file << sec);
		return;
	}

	//проверяем что параметр существует
	if (files[file][sec].find(par) == files[file][sec].end()) {
		if (needopen) { Unload(file, res); }
		res=5;
		emit SetCurrentError(res, "CoreIni::DelParam", QStringList() << file << sec << par);
		return;
	}

	//удаляем параметр
	files[file][sec].erase(par);

	//провеяем был ли загружен файл и если был - закрываем
	if (needopen) {
		//выгружаем файл
		Unload(file, res);
		if (res > 0) {
			res=7;
			emit SetCurrentError(res, "CoreIni::DelParam", QStringList() << file);
			return;
		}
	}

	res = 0;
	emit SetCurrentError(res, "CoreIni::DelParam", QStringList());
}

void CoreIni::DelParam(const QString& file, const QString& sec, const QString& par, bool& res) {
	int r;
	DelParam(file, sec, par, r);
	res = (r <= 0);
}

void CoreIni::DelParam(const QString& file, const QString& sec, const QString& par) {
	int r;
	DelParam(file, sec, par, r);
}
